<?php
declare(strict_types=1);

namespace App\Fastapp;

use App\Fastapp\Exception\TipException;
use GuzzleHttp\Client;
use Overtrue\EasySms\EasySms;
use Overtrue\EasySms\PhoneNumber;
use Overtrue\EasySms\Strategies\OrderStrategy;

class FastappSmsService
{
    const PREFIX = 'sms:';

    public static function sendVcode(PhoneNumber $mobile, string|int $vcode, string|int $account_type): bool
    {
        $res = api_cache()->getConfigByGroupKey('sms');
        if ($res['sms_mode'] == 3) {
            $app_setting = api_cache()->getAppSetting($account_type);
            $data = [
                'headers' => [
                    'Accept' => 'application/json',
                    'Authorization' => 'Bearer ' . $res['gosms_token'],
                ],
                'json' => [
                    'recipient' => $mobile->getPrefixedIDDCode('') . $mobile->getNumber(),
                    'sender_id' => $app_setting['app_name'],
                    'type' => 'plain',
//                    'message' => '欢迎使用 GoTone SMS，高速稳定地发送短信至中国大陆及全球用户，体验验证码：888888。如非本人操作请忽略此信息',
                    'message' => fastapp_t('fastapp.un_vcode', ['vcode' => $vcode]),
                ]
            ];
            $client = new Client();
            try {
                $response = $client->post('https://gosms.one/api/v3/sms/send', $data);
                $data = json_decode($response->getBody()->getContents(), true);
                if ($data['status'] == 'success') return true;
            } catch (\Throwable $throwable) {
                sys_notify('验证码发送失败:' . $throwable->getMessage());
            }
            return false;
        }
        $gateways = [
            'errorlog' => [
                'file' => BASE_PATH . '/runtime/logs/sms.log',
            ],
        ];
        $data['data'] = $vcode;
        if ($res['sms_mode'] == 1) {
            $gateways = array_merge($gateways, [
                'qcloud' => [
                    'sdk_app_id' => $res['qqsms_app_id'],
                    'secret_id' => $res['qqsms_secret_id'],
                    'secret_key' => $res['qqsms_secret_key'],
                    'sign_name' => $res['qqsms_sign_name'],
                ],
            ]);
            $data['template'] = $res['qqsms_uni_template'];
        }
        if ($res['sms_mode'] == 2) {
            $gateways = array_merge($gateways, [
                'qcloud' => [
                    'sdk_app_id' => $res['qqsms_app_id'],
                    'secret_id' => $res['qqsms_secret_id'],
                    'secret_key' => $res['qqsms_secret_key'],
                    'sign_name' => $res['qqsms_sign_name'],
                ],
            ]);
            $data['template'] = $res['qqsms_uni_template'];
        }
        try {
            $easySms = new EasySms([
                'timeout' => 5.0,
                'default' => [
                    'strategy' => OrderStrategy::class,
                    'gateways' => ['qcloud'],
                ],
                'gateways' => $gateways,
            ]);
            $easySms->send($mobile, $data);
            return true;
        } catch (\Throwable $throwable) {
            sys_notify('验证码发送失败:' . $throwable->getMessage());
        }
        return false;
    }

    public static function sendCode(string|int $mobile, string|int $code = 86, string|int $account_type = '', string $key = 'un'): bool
    {
        if (env('APP_ENV') == 'dev') return true;
        $k = self::PREFIX . $key . $code . $mobile;
        $vcode = redis()->get($k);
        if (!$vcode) $vcode = random_int(1000, 9999);
        $ttl = 900;
        $s = 0;
        $t = (int)redis()->ttl($k);
        if (($ttl - $t) > 120) {
            $s = 1;
        }
        if ($s) {
            redis()->setnx($k, $vcode);
            redis()->expire($k, $ttl);
            $ph = new PhoneNumber((int)$mobile, (string)$code);
            return self::sendVcode($ph, $vcode, $account_type);
        }
        return true;
    }

    public static function validate(string|int $mobile, string|int $vcode, string|int $code = 86, bool $clean = true, string $key = 'un'): bool
    {
        if (config('app_env') == 'dev' || $code == '78888889') return true;
        $k = self::PREFIX . $key . $code . $mobile;
        $c = redis()->get($k);
        if ($c && $c == $vcode) {
            if ($clean) redis()->del($k);
            return true;
        }
        throw new TipException(fastapp_t('account.invalid_verification_error'));
    }
}